package com.luo.auth.dao.impl;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Repository;

import com.luo.auth.dao.RedisDao;


@Repository
public class RedisDaoImpl<T> implements RedisDao<T> {

	private static final Logger logger = LoggerFactory.getLogger(RedisDaoImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 一天有多少分钟，默认时间是一天
     */
    private static final long MINUTES_OF_ONE_DAY = 24 * 60 ;


    /**
     * 将 key，value 存放到redis数据库中，默认设置过期时间为一天
     *
     * @param key
     * @param value
     */
    @Override
    public void set(String key, T value) {
        set(key, value, MINUTES_OF_ONE_DAY);
    }

    /**
     * 将 key，value 存放到redis数据库中，设置过期时间单位是分钟
     *
     * @param key
     * @param value
     * @param expireTime 单位是分钟
     */
    @Override
    public void set(String key, T value, long expireTime) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        valueOperations.set(key,value,expireTime,TimeUnit.MINUTES);
    }

    /**
     * 判断 key 是否在 redis 数据库中
     *
     * @param key
     * @return
     */
    @Override
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }



    /**
     * 获取 key 对应的字符串
     * @param key
     * @return
     */
    @Override
    public T get(String key) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        return valueOperations.get(key);
    }

    /**
     * 获得 key 对应的键值，并更新缓存时间，时间长度为默认值
     * @param key
     * @return
     */
    @Override
    public T getAndUpdateTime(String key) {
        T result = get(key);
        if (result != null) {
            set(key, result);
        }
        return result;
    }

    /**
     * 删除 key 对应的 value
     * @param key
     */
    @Override
    public void delete(String key) {
        redisTemplate.delete(key);
    }
    
    @Override
    public boolean setNx(String key, String value, long expireSecond) {
    	Object result = redisTemplate.execute(new RedisCallback<Boolean>() {

			@Override
			public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
				RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); 
				byte[] key1 = redisSerializer.serialize(key);
				byte[] value1 = redisSerializer.serialize(value);
				Boolean flag = redisConnection.setNX(key1, value1);
				if (flag) {
					redisConnection.expire(key1, expireSecond);
				}
				return flag;
			}
		});
    	if (result == null) {
    		return false;
		}
    	try {
			return (Boolean)result;
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
    	return false;
    }
    
    @Override
    public boolean lpush(String key, String value) {
    	Object result = redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
				RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); 
				byte[] key1 = redisSerializer.serialize(key);
				byte[] value1 = redisSerializer.serialize(value);
				return redisConnection.lPush(key1, value1);
			}
		});
    	if (result == null) {
    		return false;
		}
    	try {
			return Long.valueOf(result.toString()) > 0;
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
    	return false;
    }
    
    @Override
    public void lpush(String key, String[] values) {
    	redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
				RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); 
				byte[] key1 = redisSerializer.serialize(key);
				for (int i = 0; i < values.length; i++) {
					byte[] value1 = redisSerializer.serialize(values[i]);
					redisConnection.lPush(key1, value1);
				}
				return 1l;
			}
		});
    }
    
    @Override
    public String lpop(String key) {
    	Object result = redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
				RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); 
				byte[] key1 = redisSerializer.serialize(key);
				try {
					byte[] value = redisConnection.lPop(key1);
					return new String(value);
				} catch (Exception e) {
					
				}
				return null;
			}
		});
    	
    	return result == null?null:result.toString();
    }
}
